macroScript UVSetEditor
	category:"Custom"
	internalCategory:"Custom" 
	tooltip:"UV Set Editor"
	ButtonText:"UVSetEditor" 
	autoUndoEnabled:false
	Icon:#("UVWUnwrapSelection",28)
(	

	--variables related to the file naming and paths for saving defaults
	local ScriptName = "UVSetEditor"
	local ScriptsFolder = pathconfig.getdir #userscripts		
	local DefaultsFolder = pathconfig.appendPath ScriptsFolder "\\UnwrapTools"
	local DefaultsFilePath = pathconfig.appendPath DefaultsFolder ("\\" + ScriptName + "_Defaults.ini")	
	local UnwrapDirectory = pathconfig.appendPath (pathconfig.getdir #maxData) "\\plugcfg_ln\\unwrapuvw.ini"		
	
	global UVSetEditorRollout
	
	----------------------------------------------------------------------------------------------------------------------------------
	------------------------------------------ SAVE & LOAD DEFAULTS FUNTIONS ------------------------------------------
	----------------------------------------------------------------------------------------------------------------------------------	
	--A function which is used to save defaults to a file
	fn SaveToFile FilePath SectionString KeyString ValueString =
	(		
		local theFile = FilePath as string		
		local theSection = SectionString as string
		local theKey = KeyString  as string
		local theValue = ValueString as string
		
		if not doesFileExist theFile then
		(
			--take directory path part of a full file name
			local Directory = getFilenamePath theFile
			--Create a directory
			makeDir Directory			
			--OutPut to log
			format "Directory % has been created\n" Directory
		)		
		
		--if write sucessfull
		if (setINISetting theFile theSection theKey theValue) then		
		format "File has been updated sucessfully in %\n" theFile
		else	
		format "ERROR: File was not saved in %\n" theFile		
	)--end of function
	
	--Function that return value by its name which was readed from ini file.
	fn LoadValueFromFile FilePath SectionString KeyString =
	(
		local theFile = FilePath as string		
		local theSection = SectionString as string
		local theKey = KeyString  as string
		
		-- If file is not exists
		if not doesFileExist theFile then
		(
			return undefined
		)
		
		return getINISetting theFile theSection theKey
	)--end of function	

	----------------------------------------------------------------------------------------------------------------------------------
	-------------------------------------------------- UTILITY FUNCTIONS ----------------------------------------------------
	----------------------------------------------------------------------------------------------------------------------------------	
	
	--Return how many UV Channel does object have
	fn getNumUVChannels obj = 
	(
		if (isKindOf obj GeometryClass) == false do return undefined
		
		local count = 0
				
		local objMesh = obj.mesh 
		
		/*for i in 1 to meshOp.getNumMaps objMesh do
		if meshOp.getMapSupport objMesh i then*/
		count = meshOp.getNumMaps objMesh

		return (count-1)
	)-- end of function
	
	--Return a specific name of a UV Set from a provided ID
	fn GetSpecificUVSetFromObj id obj =
	(		
		local uvName = (getUserProp obj ("MapChannel:" + id as string))						
		return uvName	
	)-- end of function
	
	--Return array of names of UV Channels from obj
	fn GetUVSetsFromObj obj =
	(		
		UVSetEditorRollout.UVSetsListBox.items = #()
		local arr = #()			

		try
		(
			local numUVs = getNumUVChannels obj			
			if numUVs == 0 do return false
			
		
			for i = 1 to numUVs do 
			(
				local uvName = (getUserProp obj ("MapChannel:" + i as string))				
								
				if uvName == "" or uvName == undefined then 
				(
					append arr (i as string + ": " + "-No Name-")
				)
				else 
				(
					append arr (i as string + ": " + uvName as string)
				)
			)			
		)	catch()				
		return arr	
	)-- end of function
	
	----------------------------------------------------------------------------------------------------------------------------------
	----------------------------------------------------------------------------------------------------------------------------------
	----------------------------------------------------------------------------------------------------------------------------------
	-------------------------------------- ROLLOUT RenameUVSetRollout DEFINITION--------------------------------------
	----------------------------------------------------------------------------------------------------------------------------------
	----------------------------------------------------------------------------------------------------------------------------------	
	----------------------------------------------------------------------------------------------------------------------------------
	--Rollout RenameUVSet Definition
	rollout RenameUVSetRollout "Rename UV Set" width:350 height:110
	(
		--local variables
		local str = if isKindOf str String then str else "Default"

		--Interface					
		edittext NameEdTxt "Enter a new name:" pos:[25,15] fieldWidth:300 labelOnTop:true 
		
		button OkBtn "OK" pos:[90,70] width:85 height:25 tooltip: "" 
		button CancelBtn "Cancel" pos:[180,70] width:85 height:25 tooltip: ""

		----------------------------------------------------------------------------------------------------------------------------------
		------------------------------------------------ DIALOG INITIALIZATION -----------------------------------------------
		----------------------------------------------------------------------------------------------------------------------------------
		
		on RenameUVSetRollout open do
		(
			NameEdTxt.text = str			
		)

		----------------------------------------------------------------------------------------------------------------------------------
		------------------------------------------------------ DIALOG EVENTS ------------------------------------------------------
		----------------------------------------------------------------------------------------------------------------------------------
		
		/*on NameEdTxt entered str do 
		(
			UVSetEditorRollout.RenameUVSet str
			try(destroyDialog RenameUVSetRollout)catch()
		)*/ --this shit doesnt work if you type something and press cancel so i got rid from it
		
		on OkBtn pressed do 
		(
			str = NameEdTxt.text
			UVSetEditorRollout.RenameUVSet str
			try(destroyDialog RenameUVSetRollout)catch()
		)
		
		
		on CancelBtn pressed do
		(
			try(destroyDialog RenameUVSetRollout)catch()
		)
	)

		----------------------------------------------------------------------------------------------------------------------------------
		----------------------------------------------------------------------------------------------------------------------------------
		----------------------------------------------------------------------------------------------------------------------------------
		---------------------------------------- DIALOG UVSetEditorRollout DEFINITION --------------------------------------
		----------------------------------------------------------------------------------------------------------------------------------
		----------------------------------------------------------------------------------------------------------------------------------
		----------------------------------------------------------------------------------------------------------------------------------
	
	--Rollout UVSetEditorRollout Definition
	rollout UVSetEditorRollout "UV Set Editor" width:270 height:290
	(

	-- ROLLOUT FUNCTIONS 
	
		--Updating UVSetsListBox with UV Channels which are present in a selected object
		fn UpdateUVSetList =
		(
			local UVSets = GetUVSetsFromObj $			
			
			if UVSets != false then
			(
				UVSetEditorRollout.UVSetsListBox.items = UVSets
			)
			else 
			(
				UVSetEditorRollout.UVSetsListBox.items = #()
			)
		)-- end of function
	
		--Return real index of specific UV channel for Unwrap UVW (0 - is 1st UV channel, 1 is reserved for vertex channel)
		fn GetUVChannelIndex =
		(
			if UVSetEditorRollout.UVSetsListBox.selection == 1 then return 0 else return UVSetEditorRollout.UVSetsListBox.selection
		)-- end of function
	
		
		fn RenameUVSet newname =
		(
			local id = UVSetEditorRollout.UVSetsListBox.selection
			channelInfo.NameChannel $ 3 id newname
			UVSetEditorRollout.UpdateUVSetList()
		)			
		
		
		fn UVChannelSilentReset UVWMod =
		--Press Reset UVW in Unwrap and close pop-up window
		(
			
			--Press "Yes" in pop-up window
			fn confirmReset =
			(
				local hwnd = dialogMonitorOps.getWindowHandle()

				if UIAccessor.GetWindowText hwnd == "Unwrap UVW" then
				(					
					--uiAccessor.pressDefaultButton() -- stopped working for max 2022										
					UIAccessor.SendMessageID hwnd #IDYES --fix for max 2022
					true				
				)
				else false
			)-- end of function
			
			dialogMonitorOps.unRegisterNotification id:#unwrap_reset
			dialogMonitorOps.enabled = true
			dialogMonitorOps.interactive = false
			dialogMonitorOps.registerNotification confirmReset id:#unwrap_reset
			UVWMod.reset()
			dialogMonitorOps.enabled = false
		)-- end of function
		
		
		
		--Interface			
		listbox UVSetsListBox "UV Sets:" pos: [10,15] width:160 height:15 toolTip:""
		
		button NewBtn "New" pos:[175,30] width:85 height:25 tooltip: "Create new UV Set" 
		button EditBtn "Edit" pos:[175,60] width:85 height:25 tooltip: "Edit selected UV Set using Unwrap UVW"
		button RenameBtn "Rename" pos:[175,90] width:85 height:25 tooltip: "Rename selected UV Set"
		button DeleteBtn "Clear" pos:[175,120] width:85 height:25 tooltip: "Clear selected UV Set\nIf it is a last UV set in the list - it will be deleted\n1st UV Set can't be deleted or cleared" 
		button DuplicateBtn "Duplicate" pos:[175,150] width:85 height:25 tooltip: "Duplicate UV Set"
		button CopyBtn "Copy" pos:[175,180] width:85 height:25 tooltip: "Copy UVs from selected UV Set in clipboard"
		button PasteBtn "Paste" pos:[175,210] width:85 height:25 tooltip: "Paste UVs in selected UV Set from clipboard"
						
		groupBox grpline "" pos:[5,235] width:260 height:8
		
		button UpdateBtn "Update" pos:[10,250] width:120 height:30 tooltip: "Update list of UV Sets" 
		button CloseBtn "Close" pos:[140,250] width:120 height:30 tooltip: "Close this window" 
		
		----------------------------------------------------------------------------------------------------------------------------------
		------------------------------------------------ DIALOG INITIALIZATION -----------------------------------------------
		----------------------------------------------------------------------------------------------------------------------------------
		
		--Initialize variables on start
		on UVSetEditorRollout open do
		(		
			try
			(					
				--update UVSetList
				UpdateUVSetList()
				
				--setting callback to update list when selection is changing
				try (callbacks.removeScripts id:#UpdateUVSetList) catch()
				callbacks.addScript #selectionSetChanged "UVSetEditorRollout.UpdateUVSetList()" id:#UpdateUVSetList
								
				--if selection.count != 0 do
				
			)
			catch ()			

		) --End initialize
		
	----------------------------------------------------------------------------------------------------------------------------------
	------------------------------------------------------ DIALOG EVENTS ------------------------------------------------------
	----------------------------------------------------------------------------------------------------------------------------------
		--User pressed New button
		on NewBtn pressed do 
		(
			channelInfo.addChannel $
			local UVNum = getNumUVChannels $
			local StrName = "map" + UVNum as string
			channelInfo.NameChannel $ 3 UVNum StrName
			UpdateUVSetList()
			UVSetsListBox.selection = UVSetsListBox.items.count
		)
		
		--User pressed Update button
		on UpdateBtn pressed do 
		(
			UpdateUVSetList()
		)
		
		--User pressed Delete button
		on DeleteBtn pressed do
		(
			local UVSetSelection = UVSetsListBox.selection
			if UVSetSelection != 1 do 
			(
				if UVSetsListBox.selection == UVSetsListBox.items.count then
				(
					channelInfo.ClearChannel $ UVSetSelection
					UVSetsListBox.selection = UVSetSelection-1
				)
				else
				(					
					channelInfo.ClearChannel $ UVSetSelection
					local StrName = "map" + UVSetSelection as string
					channelInfo.NameChannel $ 3 UVSetSelection StrName
					UpdateUVSetList()
				)
			)
		)
		
		--User pressed Edit button
		on EditBtn pressed do 
		(
			local uvw_mod = modpanel.getcurrentobject()
			local UVChannel = GetUVChannelIndex()
			
			--if uvw_mod != undefined and classof (uvw_mod) == Unwrap_UVW then
			if classof (uvw_mod) == Unwrap_UVW and uvw_mod.getMapChannel() == UVChannel then
			(
				uvw_mod.edit()
			)
			else 
			(
				modPanel.addModToSelection (Unwrap_UVW ()) ui:on	
				uvw_mod = modpanel.getcurrentobject()
				uvw_mod.unwrap.setMapChannel UVChannel
				UVChannelSilentReset uvw_mod
				uvw_mod.edit()				
			)
		)
		
		--User pressed Close button
		on CloseBtn pressed do
		(
			try(destroyDialog UVSetEditorRollout)catch()
		)
		
		--User pressed Rename button
		on RenameBtn pressed do 
		(
			local theDialogPos = GetDialogPos UVSetEditorRollout
			theDialogPos.x -=  40
			theDialogPos.y += UVSetEditorRollout.height/2-30
			
			local UVSetName = GetSpecificUVSetFromObj UVSetsListBox.selection $
			
			RenameUVSetRollout.Str = UVSetName
			createDialog RenameUVSetRollout pos:[theDialogPos.x,theDialogPos.y] parent:UVSetEditorRollout.hwnd style:#(#style_toolwindow, #style_sysmenu) modal:true			
			
		)
		
		--User pressed Duplicate button
		on DuplicateBtn pressed do 
		(
			ChannelInfo.CopyChannel $ 3 UVSetsListBox.selection
			
			channelInfo.addChannel $
			local UVNum = getNumUVChannels $
			local StrName = "map" + UVNum as string
			channelInfo.NameChannel $ 3 UVNum StrName
			
			ChannelInfo.PasteChannel $ 3 UVNum
						
			UpdateUVSetList()
			UVSetsListBox.selection = UVSetsListBox.items.count
		)
		
		on CopyBtn pressed do 
		(
			ChannelInfo.CopyChannel $ 3 UVSetsListBox.selection
		)
		
		on PasteBtn pressed do 
		(
			ChannelInfo.PasteChannel $ 3 UVSetsListBox.selection
		)
	
	
				
	----------------------------------------------------------------------------------------------------------------------------------
	------------------------------------------------- SAVE DEFAULTS TO FILE -------------------------------------------------
	----------------------------------------------------------------------------------------------------------------------------------			
				
		--when user closing this window
		on UVSetEditorRollout close do 
		(									
			--getting dialog position
			local theDialogPos = GetDialogPos UVSetEditorRollout
			
			--saving settings to a file		
			SaveToFile DefaultsFilePath "Defaults" "DialogPositionX" theDialogPos.x
			SaveToFile DefaultsFilePath "Defaults" "DialogPositionY" theDialogPos.y		
			
			--remove callback
			try(callbacks.removeScripts id:#UpdateUVSetList)catch()
			
		)
	)--End of Rollout Definition
		
	
	--When script is launching
	on execute do 
	(
			--Try to destroy previous rollout
			try(destroyDialog UVSetEditorRollout)catch()
			
			try
			(
				local DialogPositionX = LoadValueFromFile DefaultsFilePath "Defaults" "DialogPositionX" as integer
				local DialogPositionY = LoadValueFromFile DefaultsFilePath "Defaults" "DialogPositionY" as integer
			)
			catch()
			
			--OpenDialog			
			if (DialogPositionX != undefined) and (DialogPositionY != undefined) then
			(				
				--load postion from file
				createDialog UVSetEditorRollout Pos: [DialogPositionX,DialogPositionY]	style:#(#style_toolwindow, #style_sysmenu)
			)
			else 
			(
				--start from the default postion
				createDialog UVSetEditorRollout Pos: [1300,230] style:#(#style_toolwindow, #style_sysmenu)
			)		
	)
)